import 'package:dio/dio.dart';
import 'package:get_storage/get_storage.dart';
import 'package:jss_flutter/app/config/http_options.dart';
import 'package:jss_flutter/http/error_interceptor.dart';
import 'package:jss_flutter/http/global.dart';
import 'package:jss_flutter/utils/log_utils.dart';
import 'package:logger/logger.dart';

/// http 请求单例类
class HttpRequest {
  // 工厂构造方法
  factory HttpRequest() => _instance;

  // 初始化一个单例实例
  static final HttpRequest _instance = HttpRequest._internal();

  // dio 实例
  late final Dio _dio;

  // 内部构造方法
  HttpRequest._internal() {
    if (_dio == null) {
      // BaseOptions、Options、RequestOptions 都可以配置参数，优先级别依次递增，且可以根据优先级别覆盖参数
      BaseOptions baseOptions = BaseOptions(
        baseUrl: HttpOptions.BASE_URL,
        connectTimeout: HttpOptions.CONNECT_TIMEOUT,
        receiveTimeout: HttpOptions.RECEIVE_TIMEOUT,
        headers: {},
      );
      // 没有实例 则创建之
      _dio = Dio(baseOptions);
      // 添加拦截器
      _dio.interceptors.add(ErrorInterceptor());
      _dio.interceptors.add(LogInterceptor());
    }
  }

//参考第二种单例写法
//   class Manager {
//   // 工厂模式
//   factory Manager.shared() =>_getInstance();
//   static Manager get instance => _getInstance();
//   static Manager _instance;
//   Manager._internal() {
//   // 初始化
//   }
//   static Manager _getInstance() {
//   _instance ??= Manager._internal();
//   return _instance;
//   }
//   }
// 调用
//   Manager manager = Manager.shared();

  /// 初始化公共属性 如果需要覆盖原配置项 就调用它
  ///
  /// [baseUrl] 地址前缀
  /// [connectTimeout] 连接超时赶时间
  /// [receiveTimeout] 接收超时赶时间
  /// [headers] 请求头
  /// [interceptors] 基础拦截器
  void init({
    String? baseUrl,
    int? connectTimeout,
    int? receiveTimeout,
    Map<String, dynamic>? headers,
    List<Interceptor>? interceptors,
  }) {
    _dio.options.connectTimeout = connectTimeout!;
    _dio.options.receiveTimeout = receiveTimeout!;
    _dio.options.headers = headers;
    if (interceptors != null && interceptors.isNotEmpty) {
      _dio.interceptors.addAll(interceptors);
    }
  }

  /// 设置请求头
  void setHeaders(Map<String, dynamic> headers) {
    _dio.options.headers.addAll(headers);
  }

  final CancelToken _cancelToken = CancelToken();

  /*
   * 取消请求
   *
   * 同一个cancel token 可以用于多个请求
   * 当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  void cancelRequests({CancelToken? token}) {
    token ?? _cancelToken.cancel("cancelled");
  }

  /// 设置鉴权请求头
  Map<String, dynamic> _getAuthorizationHeader() {
    var headers;
    String _token = Global.accessToken;
    if (_token.isEmpty) {
      LogUtils.d("token is empty");
      var storageBox = GetStorage();
      _token = storageBox.read("token");
      Global.accessToken = _token;
      LogUtils.d("token=${Global.accessToken}");
    }
    if (_token.isNotEmpty) {
      headers = {
        'token': _token,
      };
    }
    return headers;
  }

  /// 设置鉴权请求头
  Options setAuthorizationHeader(Options requestOptions) {
    String _token = Global.accessToken;
    if (_token.isEmpty) {
      LogUtils.d("token is empty");
      var storageBox = GetStorage();
      _token = storageBox.read("token");
      Global.accessToken = _token;
      LogUtils.d("token=${Global.accessToken}");
    }
    LogUtils.e("requestOptions.headers= ${requestOptions.headers}");
    if (_token.isNotEmpty) {
      LogUtils.d("token1= $_token");
      requestOptions.headers?['token'] = _token;
    }
    return requestOptions;
  }

  /// restful get 操作
  Future get(
    String path, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = setAuthorizationHeader(options ?? Options());
    Response response = await _dio.get(
      path,
      queryParameters: params,
      options: requestOptions,
      cancelToken: cancelToken ?? _cancelToken,
    );
    return response.data;
  }

  /// restful post 操作
  Future post(
    String path, {
    Map<String, dynamic>? params,
    dynamic data,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic> _authorization = _getAuthorizationHeader();
    requestOptions = requestOptions.copyWith(headers: _authorization);
    Response response = await _dio.post(
      path,
      data: data,
      queryParameters: params,
      options: requestOptions,
      cancelToken: cancelToken ?? _cancelToken,
    );
    return response.data;
  }

  /// restful post form 表单提交操作
  Future postForm(
    String path, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Options requestOptions = options ?? Options();
    Map<String, dynamic> _authorization = _getAuthorizationHeader();
    requestOptions = requestOptions.copyWith(headers: _authorization);
    Response response = await _dio.post(
      path,
      data: FormData.fromMap(params!),
      options: requestOptions,
      cancelToken: cancelToken ?? _cancelToken,
    );
    return response.data;
  }
}
